LVGL官方Demo全解析:从音乐播放器到高分辨率渲染
// 头文件引入
#include "lvgl/lvgl.h" // LVGL核心库
#include "lvgl/demos/lv_demos.h" // LVGL官方示例(后续不需要demo可以去掉)
#include <unistd.h> // 系统调用(如usleep)
#include <pthread.h> // 线程支持
#include <time.h> // 时间函数
#include <stdio.h> // 标准输入输出
#include <stdlib.h> // 标准库(如atoi, getenv)
// 安全获取环境变量(如显示设备路径或窗口尺寸),避免空指针错误
static const char *getenv_default(const char *name, const char *dflt)
{
return getenv(name) ? : dflt;// 获取环境变量,不存在则返回默认值
}
// 显示设备初始化(条件编译)
// 因为lv_conf.h中已经设置LV_USE_LINUX_FBDEV为1,所以这里只会编译第一块
#if LV_USE_LINUX_FBDEV
static void lv_linux_disp_init(void)
{
const char *device = getenv_default("LV_LINUX_FBDEV_DEVICE", "/dev/fb0");
lv_display_t * disp = lv_linux_fbdev_create();
lv_linux_fbdev_set_file(disp, device);
}
#elif LV_USE_LINUX_DRM
static void lv_linux_disp_init(void)
{
const char *device = getenv_default("LV_LINUX_DRM_CARD", "/dev/dri/card0");
lv_display_t * disp = lv_linux_drm_create();
lv_linux_drm_set_file(disp, device, -1);
}
#elif LV_USE_SDL
static void lv_linux_disp_init(void)
{
const int width = atoi(getenv("LV_SDL_VIDEO_WIDTH") ? : "800");
const int height = atoi(getenv("LV_SDL_VIDEO_HEIGHT") ? : "480");
lv_sdl_window_create(width, height);
}
#else
#error Unsupported configuration
#endif
int main(void)
{
lv_init(); // 初始化LVGL库(内存管理、定时器等)
/*Linux display device init*/
// 显示设备初始化
lv_linux_disp_init();
// 输入设备初始化
lv_indev_t * indev = lv_evdev_create(LV_INDEV_TYPE_POINTER, "/dev/input/event0");
/*Create a Demo*/
// 加载官方控件示例
lv_demo_widgets();
// 启动自动幻灯片演示,注释掉以取消滚动
//lv_demo_widgets_start_slideshow();
/*Handle LVGL tasks*/
// 主事件循环
while(1) {
lv_timer_handler(); // 处理LVGL任务(渲染、输入、动画)
usleep(5000); // 休眠5ms(约200Hz刷新率)
}
return 0;
}
lv_conf.h中V_USE_DEMO_MUSIC默认设为1,不用更改,但是可以更改一些参数 【谨慎修改,修改lv_conf.h会导致需要重新编译lvgl】 【横屏显示器启用其他布局效果不明显】
** Music player demo */
#define LV_USE_DEMO_MUSIC 1
#if LV_USE_DEMO_MUSIC
#define LV_DEMO_MUSIC_SQUARE 0 // 启用方形布局
#define LV_DEMO_MUSIC_LANDSCAPE 0 // 启用横向布局
#define LV_DEMO_MUSIC_ROUND 0 // 启用圆形布局
#define LV_DEMO_MUSIC_LARGE 0 // 启用大屏布局
// 默认使用横向布局,
#define LV_DEMO_MUSIC_AUTO_PLAY 0 // 禁用自动播放
#endif
修改main.c 中 / * Create a Demo* / 区块
/*Create a Demo*/
//lv_demo_widgets();
//lv_demo_widgets_start_slideshow();
lv_demo_music();
lv_conf.h
/** Benchmark your system */
#define LV_USE_DEMO_BENCHMARK 1 // 启用Benchmark Demo
#if LV_USE_DEMO_BENCHMARK
/** Use fonts where bitmaps are aligned 16 byte and has Nx16 byte stride */
#define LV_DEMO_BENCHMARK_ALIGNED_FONTS 0 // 默认禁用字体对齐优化
#endif
main.c
lv_demo_benchmark(); //(测量渲染效率)
lv_conf.h
/** Stress test for LVGL */
#define LV_USE_DEMO_STRESS 1
main.c
lv_demo_stress(); //(创建大量对象检验稳定性)
lv_conf.h
/** Demonstrate usage of encoder and keyboard. */
#define LV_USE_DEMO_KEYPAD_AND_ENCODER 1
main.c
lv_demo_keypad_and_encoder(); // (非触控设备)
lv_conf.h
/** Render test for each primitive.
* - Requires at least 480x272 display. */
#define LV_USE_DEMO_RENDER 1
main.c
lv_conf.h
/** Vector graphic demo */
// 默认禁用
#define LV_USE_DEMO_VECTOR_GRAPHIC 0
main.c
注:高级demo需要下载另一个仓库: 仓库地址:lvgl/lv_demos: Examples, tutorials and applications for the LVGL embedded GUI library (github.com)
【不要下载归档,归档已经很久没更新了,请直接下载源码】
备用链接:lv_demos-master.zip - 蓝奏云 (lanzoue.com)
把解压后的src文件夹里的内容放入lvgl/demos
demo整合后的目录结构:

整合一下lv_demos.h
# 在lv_demos.h添加
#if LV_USE_DEMO_FLEX_LAYOUT
#include "flex_layout/lv_demo_flex_layout.h"
#endif
#if LV_USE_DEMO_TRANSFORM
#include "transform/lv_demo_transform.h"
#endif
#if LV_USE_DEMO_SCROLL
#include "scroll/lv_demo_scroll.h"
#endif
#if LV_USE_DEMO_MULTILANG
#include "multilang/lv_demo_multilang.h"
#endif
// 需要把LV_USE_BIDI 和LV_USE_ARABIC_PERSIAN_CHARS 置为1
#if LV_USE_DEMO_EBIKE
#include "ebike/lv_demo_ebike.h"
#endif
#if LV_USE_DEMO_HIGH_RES
#include "high_res/lv_demo_high_res.h"
#endif
// LV_USE_DEMO_HIGH_RES还要启用下面几项:
#define LV_FONT_FMT_TXT_LARGE 1
/** Setting a default driver letter allows skipping the driver prefix in filepaths.
* Documentation about how to use the below driver-identifier letters can be found at
* https://docs.lvgl.io/master/details/main-modules/fs.html#lv-fs-identifier-letters . */
#define LV_FS_DEFAULT_DRIVER_LETTER 'A'
/** API for fopen, fread, etc. */
#define LV_USE_FS_STDIO 0
#if LV_USE_FS_STDIO
#define LV_FS_STDIO_LETTER 'A'
#define LV_FS_STDIO_PATH "" /**< Set the working directory. File/directory paths will be appended to it. */
#define LV_FS_STDIO_CACHE_SIZE 0 /**< >0 to cache this number of bytes in lv_fs_read() */
#endif
/** API for open, read, etc. */
#define LV_USE_FS_POSIX 1
#if LV_USE_FS_POSIX
#define LV_FS_POSIX_LETTER 'A' /*Set an upper cased letter on which the drive will accessible (e.g. 'A')*/
#define LV_FS_POSIX_PATH "" /*Set the working directory. File/directory paths will be appended to it.*/
#define LV_FS_POSIX_CACHE_SIZE 0 /*>0 to cache this number of bytes in lv_fs_read()*/
#endif
//【后续使用模拟器时,还要修改源码lvgl\src\libs\fsdrv\lv_fs_posix.c,现在不用改】
/*添加#include <sys/stat.h>
注释掉
static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn, uint32_t fn_len)
{
LV_UNUSED(drv);
if(fn_len == 0) return LV_FS_RES_INV_PARAM;
struct dirent * entry;
do {
entry = readdir(dir_p);
if(entry) {
if(entry->d_type == DT_DIR) lv_snprintf(fn, fn_len, "/%s", entry->d_name);
else lv_strlcpy(fn, entry->d_name, fn_len);
}
else {
lv_strlcpy(fn, "", fn_len);
}
} while(lv_strcmp(fn, "/.") == 0 || lv_strcmp(fn, "/..") == 0);
return LV_FS_RES_OK;
}
修改为:
static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn, uint32_t fn_len)
{
LV_UNUSED(drv);
if(fn_len == 0) return LV_FS_RES_INV_PARAM;
struct dirent * entry;
do {
entry = readdir(dir_p);
if(entry) {
char full_path[PATH_MAX];
lv_snprintf(full_path, sizeof(full_path), "%s/%s", ((DIR *)dir_p)->dd_name, entry->d_name);
struct stat st;
if(stat(full_path, &st) == 0) {
if(S_ISDIR(st.st_mode)) {
lv_snprintf(fn, fn_len, "/%s", entry->d_name); // Add '/' prefix for directories
} else {
lv_strlcpy(fn, entry->d_name, fn_len); // No prefix for files
}
} else {
lv_strlcpy(fn, entry->d_name, fn_len); // Fallback: assume it's a file
}
}
else {
lv_strlcpy(fn, "", fn_len);
}
} while(entry && (lv_strcmp(fn, "/.") == 0 || lv_strcmp(fn, "/..") == 0));
return LV_FS_RES_OK;
}
*/
/* Smart watch demo */
#define LV_USE_DEMO_SMARTWATCH 0
lv_conf.h
/*---------------------------
* Demos from lvgl/lv_demos
---------------------------*/
/** Flex layout demo */
// 弹性布局demo。展示LVGL的Flex布局功能,类似于CSS Flexbox的布局系统
#define LV_USE_DEMO_FLEX_LAYOUT 1
/** Smart-phone like multi-language demo */
// 多语言支持demo。展示类似智能手机的多语言切换界面
#define LV_USE_DEMO_MULTILANG 1
/** Widget transformation demo */
// 小部件变换demo。展示各种变换效果
#define LV_USE_DEMO_TRANSFORM 1
/** Demonstrate scroll settings */
// 滚动设置演示demo。展示LVGL的各种滚动效果和设置
#define LV_USE_DEMO_SCROLL 1
/*E-bike demo with Lottie animations (if LV_USE_LOTTIE is enabled)*/
电动自行车仪表盘demo(需要启用LV_USE_LOTTIE)。有纵向和横向两种显示模式
#define LV_USE_DEMO_EBIKE 0
#if LV_USE_DEMO_EBIKE
#define LV_DEMO_EBIKE_PORTRAIT 0 /*0: for 480x270..480x320, 1: for 480x800..720x1280*/
#endif
/** High-resolution demo */
高分辨率演示demo。针对高分辨率屏幕优化
#define LV_USE_DEMO_HIGH_RES 0
/* Smart watch demo */
智能手表界面demo。模拟智能手表的各种界面和交互
#define LV_USE_DEMO_SMARTWATCH 0
main.c?
函数接口命名很规范,找规律即可
还是列出吧:
备用标题: LVGL官方Demo全解析:嵌入式GUI开发实战指南 深度解锁LVGL Demo:从音乐播放器到高分辨率渲染 LVGL Demo高效集成术:跨平台部署与性能调优 嵌入式GUI开发利器:LVGL官方Demo配置与高级应用 LVGL官方Demo全解析:从音乐播放器到高分辨率渲染